package main

import "fmt"

/*
go里面接口类似于java的接口，只定义方法，不定义实现

1.接口名：使用type将接口定义为自定义的类型名。Go语言的接口在命名时，一般会在单词后面添加er，如有写操作的接口叫Writer，有字符串功能的接口叫Stringer等。接口名最好要能突出该接口的类型含义。
2.方法名：当方法名首字母是大写且这个接口类型名首字母也是大写时，这个方法可以被接口所在的包（package）之外的代码访问。
3.参数列表、返回值列表：参数列表和返回值列表中的参数变量名可以省略。

类似于java，接口可以继承其他接口，接口也可以通过类（结构体）的之间的继承传递

go中的空接口 interface{} , 任何类型都实现了它，所以空接口可以存储任何类型的变量（类似于java中的Object类）
*/

//定义一个Sayer接口
type Sayer interface {
	say(content string)
}

//定义Dog和Cat两个结构体
type Dog struct{}
type Cat struct{}

// dog实现了Sayer接口，是指针类型接收方法
func (d *Dog) say(content string) {
	fmt.Println("狗说：" + content)
}

// cat实现了Sayer接口，是值类型接收方法
func (c Cat) say(content string) {
	fmt.Println("猫说：" + content)
}

func main() {
	dog := new(Dog)
	dog.say("汪汪汪")

	cat := Cat{}
	cat.say("喵喵喵")

	//接口赋值
	var x Sayer    // 声明一个Sayer类型的变量x
	a := Cat{}     // 实例化一个cat
	b := Dog{}     // 实例化一个dog
	x = a          // 可以把cat实例直接赋值给x，
	x = &a         // 可以把cat的指针直接赋值给x，
	x.say("hello") // 喵喵喵
	x = &b         // 只能把dog指针直接赋值给x
	x.say("hello") // 汪汪汪
}
